Completed
Pull Request — master (#237)
by Alejandro
06:57
created

CreateShortUrl.js ➔ render   C

Complexity

Conditions 6

Size

Total Lines 115
Code Lines 105

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6.0585

Importance

Changes 0
Metric Value
eloc 105
dl 0
loc 115
ccs 15
cts 17
cp 0.8824
rs 6.0666
c 0
b 0
f 0
cc 6
crap 6.0585

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import { faAngleDoubleDown as downIcon, faAngleDoubleUp as upIcon } from '@fortawesome/free-solid-svg-icons';
2
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
import { isEmpty, isNil, pipe, replace, trim } from 'ramda';
4
import React, { useState } from 'react';
5
import { Collapse, FormGroup, Input } from 'reactstrap';
6
import * as PropTypes from 'prop-types';
7
import DateInput from '../utils/DateInput';
8
import Checkbox from '../utils/Checkbox';
9
import { serverType } from '../servers/prop-types';
10
import { versionMatch } from '../utils/helpers/version';
11
import { hasValue } from '../utils/utils';
12
import { useToggle } from '../utils/helpers/hooks';
13
import { createShortUrlResultType } from './reducers/shortUrlCreation';
14
import UseExistingIfFoundInfoIcon from './UseExistingIfFoundInfoIcon';
15
16 1
const normalizeTag = pipe(trim, replace(/ /g, '-'));
17 2
const formatDate = (date) => isNil(date) ? date : date.format();
18
19 1
const propTypes = {
20
  createShortUrl: PropTypes.func,
21
  shortUrlCreationResult: createShortUrlResultType,
22
  resetCreateShortUrl: PropTypes.func,
23
  selectedServer: serverType,
24
};
25
26 1
const CreateShortUrl = (TagsSelector, CreateShortUrlResult, ForServerVersion) => {
27 1
  const CreateShortUrlComp = ({ createShortUrl, shortUrlCreationResult, resetCreateShortUrl, selectedServer }) => {
28 9
    const [ shortUrlCreation, setShortUrlCreation ] = useState({
29
      longUrl: '',
30
      tags: [],
31
      customSlug: undefined,
32
      shortCodeLength: undefined,
33
      domain: undefined,
34
      validSince: undefined,
35
      validUntil: undefined,
36
      maxVisits: undefined,
37
      findIfExists: false,
38
    });
39 9
    const [ moreOptionsVisible, toggleMoreOptionsVisible ] = useToggle(false);
40
41 9
    const changeTags = (tags) => setShortUrlCreation({ ...shortUrlCreation, tags: tags.map(normalizeTag) });
42 9
    const renderOptionalInput = (id, placeholder, type = 'text', props = {}) => (
43 36
      <FormGroup>
44
        <Input
45
          id={id}
46
          type={type}
47
          placeholder={placeholder}
48
          value={shortUrlCreation[id]}
49 4
          onChange={(e) => setShortUrlCreation({ ...shortUrlCreation, [id]: e.target.value })}
50
          {...props}
51
        />
52
      </FormGroup>
53
    );
54 9
    const renderDateInput = (id, placeholder, props = {}) => (
55 18
      <div className="form-group">
56
        <DateInput
57
          selected={shortUrlCreation[id]}
58
          placeholderText={placeholder}
59
          isClearable
60 2
          onChange={(date) => setShortUrlCreation({ ...shortUrlCreation, [id]: date })}
61
          {...props}
62
        />
63
      </div>
64
    );
65 9
    const save = (e) => {
66 1
      e.preventDefault();
67 1
      createShortUrl({
68
        ...shortUrlCreation,
69
        validSince: formatDate(shortUrlCreation.validSince),
70
        validUntil: formatDate(shortUrlCreation.validUntil),
71
      });
72
    };
73 9
    const currentServerVersion = selectedServer && selectedServer.version;
74 9
    const disableDomain = !versionMatch(currentServerVersion, { minVersion: '1.19.0-beta.1' });
75 9
    const disableShortCodeLength = !versionMatch(currentServerVersion, { minVersion: '2.1.0' });
76
77 9
    return (
78
      <form onSubmit={save}>
79
        <div className="form-group">
80
          <input
81
            className="form-control form-control-lg"
82
            type="url"
83
            placeholder="Insert the URL to be shortened"
84
            required
85
            value={shortUrlCreation.longUrl}
86 1
            onChange={(e) => setShortUrlCreation({ ...shortUrlCreation, longUrl: e.target.value })}
87
          />
88
        </div>
89
90
        <Collapse isOpen={moreOptionsVisible}>
91
          <div className="form-group">
92
            <TagsSelector tags={shortUrlCreation.tags} onChange={changeTags} />
93
          </div>
94
95
          <div className="row">
96
            <div className="col-sm-4">
97
              {renderOptionalInput('customSlug', 'Custom slug')}
98
            </div>
99
            <div className="col-sm-4">
100
              {renderOptionalInput('shortCodeLength', 'Short code length', 'number', {
101
                min: 4,
102
                disabled: disableShortCodeLength || hasValue(shortUrlCreation.customSlug),
103
                ...disableShortCodeLength && {
104
                  title: 'Shlink 2.1.0 or higher is required to be able to provide the short code length',
105
                },
106
              })}
107
            </div>
108
            <div className="col-sm-4">
109
              {renderOptionalInput('domain', 'Domain', 'text', {
110
                disabled: disableDomain,
111
                ...disableDomain && { title: 'Shlink 1.19.0 or higher is required to be able to provide the domain' },
112
              })}
113
            </div>
114
          </div>
115
116
          <div className="row">
117
            <div className="col-sm-4">
118
              {renderOptionalInput('maxVisits', 'Maximum number of visits allowed', 'number', { min: 1 })}
119
            </div>
120
            <div className="col-sm-4">
121
              {renderDateInput('validSince', 'Enabled since...', { maxDate: shortUrlCreation.validUntil })}
122
            </div>
123
            <div className="col-sm-4">
124
              {renderDateInput('validUntil', 'Enabled until...', { minDate: shortUrlCreation.validSince })}
125
            </div>
126
          </div>
127
128
          <ForServerVersion minVersion="1.16.0">
129
            <div className="mb-4 text-right">
130
              <Checkbox
131
                className="mr-2"
132
                checked={shortUrlCreation.findIfExists}
133
                onChange={(findIfExists) => setShortUrlCreation({ ...shortUrlCreation, findIfExists })}
134
              >
135
                Use existing URL if found
136
              </Checkbox>
137
              <UseExistingIfFoundInfoIcon />
138
            </div>
139
          </ForServerVersion>
140
        </Collapse>
141
142
        <div>
143
          <button type="button" className="btn btn-outline-secondary" onClick={toggleMoreOptionsVisible}>
144
            <FontAwesomeIcon icon={moreOptionsVisible ? upIcon : downIcon} />
145
            &nbsp;
146
            {moreOptionsVisible ? 'Less' : 'More'} options
147
          </button>
148
          <button
149
            className="btn btn-outline-primary float-right"
150
            disabled={shortUrlCreationResult.loading || isEmpty(shortUrlCreation.longUrl)}
151
          >
152
            {shortUrlCreationResult.loading ? 'Creating...' : 'Create'}
153
          </button>
154
        </div>
155
156
        <CreateShortUrlResult {...shortUrlCreationResult} resetCreateShortUrl={resetCreateShortUrl} />
157
      </form>
158
    );
159
  };
160
161 1
  CreateShortUrlComp.propTypes = propTypes;
162
163 1
  return CreateShortUrlComp;
164
};
165
166
export default CreateShortUrl;
167